
1. 먼저 전체 구조부터 이해하면 쉽습니다
AWS SES에서 메일을 보내는 과정은 크게 3단계 인증으로 생각하면 됩니다.
[내 서버 / 애플리케이션]
│
│ ① AWS 자격 증명
│ 또는 SES SMTP 자격 증명
▼
[AWS SES]
│
│ ② 발신 도메인 인증
│ pion79.kr
▼
[수신 메일 서버]
│
│ ③ 이메일 인증
│ SPF / DKIM / DMARC
▼
[Gmail 등]각각 목적이 다릅니다.
구분 | 무엇을 인증? | 목적 |
|---|---|---|
AWS 자격 증명 | 내 프로그램이 AWS를 사용할 권한이 있는지 | SES API 사용 권한 |
SES SMTP 자격 증명 | SMTP로 SES에 접속하는 프로그램인지 | SMTP 메일 발송 |
SES Identity 인증 | 내가 |
|
SPF | SES가 해당 도메인의 허가된 발송 서버인지 | 발신 서버 검증 |
DKIM | 메일이 SES에서 정상적으로 서명되었는지 | 메일 위변조/도메인 검증 |
DMARC | From 도메인과 SPF/DKIM이 일치하는지 | 스푸핑 방지 |
AWS도 SES API와 SMTP 인터페이스에서 사용하는 자격 증명이 서로 다르다고 명확하게 구분하고 있습니다. (AWS Documentation)
2. "자격 증명"이란?
예를 들어 현재 서버에서 이런 프로그램을 만든다고 하겠습니다.
Ubuntu 서버
↓
내 이메일 인증 프로그램
↓
AWS SES
↓
Gmail프로그램이 AWS SES에게
"나는
pion79.kr서비스를 운영하는 서버이고 메일을 보내려고 한다."
라고 요청해야 합니다.
AWS는 그냥 아무 프로그램이나 SES를 사용할 수 있게 하지 않습니다.
그래서 **자격 증명(Credentials)**이 필요합니다.
3. SES에는 크게 두 가지 방법이 있습니다
방법 A — SES API 사용
프로그램이 AWS SDK를 이용합니다.
Node.js / Python / Java
↓
AWS SDK
↓
SES API이 경우 일반적으로 AWS Access Key / Secret Access Key 또는 더 안전한 IAM 역할 등을 사용합니다.
AWS 문서에서도 SES API 접근에는 AWS Access Key ID + Secret Access Key를 사용하는 것으로 설명합니다. (AWS Documentation)
방법 B — SMTP 사용
프로그램이 일반적인 SMTP 서버처럼 SES에 접속합니다.
내 프로그램
↓
SMTP
↓
email-smtp.ap-northeast-2.amazonaws.com
↓
AWS SES이 경우 필요한 것이:
SMTP Username
SMTP Password입니다.
그리고 중요한 점이 있습니다.
SES SMTP Username/Password는 AWS 로그인 비밀번호가 아닙니다.
또한 일반적인 AWS Access Key/Secret Access Key와도 동일하지 않습니다. (AWS Documentation)
4. SES SMTP 자격 증명은 어떻게 만들어지는가?
AWS SES 콘솔에서:
SES → SMTP settings → Create SMTP credentials
를 선택하면 IAM 쪽에서 SMTP 사용자를 생성하게 됩니다.
예를 들어 개념적으로:
IAM User
│
└── ses-smtp-user
│
├── SMTP Username
└── SMTP Password이 정보를 프로그램에 넣습니다.
예:
SMTP_HOST=email-smtp.ap-northeast-2.amazonaws.com
SMTP_PORT=587
SMTP_USERNAME=xxxxxxxxxxxxxxxx
SMTP_PASSWORD=xxxxxxxxxxxxxxxxAWS 문서에 따르면 SES SMTP 자격 증명은 AWS Region별로 다릅니다. 따라서 ap-northeast-2에서 만든 SMTP 자격 증명을 다른 Region의 SES SMTP endpoint에서 그대로 사용하는 방식으로 생각하면 안 됩니다. (AWS Documentation)
5. 그런데 여기서 중요한 것이 하나 더 있습니다
SMTP 자격 증명이 있다고 해서
From: service@pion79.kr로 마음대로 메일을 보낼 수 있는 것은 아닙니다.
여기서 등장하는 것이 SES Identity 인증입니다.
6. SES Identity 인증이란?
AWS SES에서:
"이 도메인을 내가 소유하고 있다."
라는 것을 AWS에 증명하는 것입니다.
예를 들어:
pion79.kr을 SES에서 Domain Identity로 등록합니다.
그러면 AWS가 DNS에 넣어야 할 값을 알려줍니다.
예를 들어 개념적으로:
abc123._domainkey.pion79.kr
↓
abc123.dkim.amazonses.com이런 CNAME 레코드가 여러 개 나옵니다.
Cafe24 DNS에 이 값을 넣으면 AWS가 확인합니다.
AWS SES
│
│ "pion79.kr의 DNS를 확인해보자"
▼
Cafe24 DNS
│
└── DKIM CNAME확인되면:
pion79.kr
Status: Verified가 됩니다.
AWS는 도메인 Identity를 검증할 때 DNS에 DKIM 관련 레코드를 등록하도록 하고 있으며, DNS 전파에는 최대 72시간이 걸릴 수 있다고 설명합니다. (AWS Documentation)
7. 이것을 "AWS 인증"과 혼동하면 안 됩니다
아주 중요합니다.
A. SMTP 인증
내 서버
↓
SMTP Username
SMTP Password
↓
AWS SES이것은
"SES를 사용할 권한이 있는 프로그램인가?"
를 확인합니다.
B. 도메인 인증
pion79.kr
↓
DNS
↓
SES이것은
"pion79.kr을 실제로 관리하는 사람인가?"
를 확인합니다.
C. 이메일 인증
service@pion79.kr
↓
메일
↓
Gmail
↓
SPF / DKIM / DMARC 검사이것은
"이 메일이 정말 pion79.kr에서 정상적으로 발송된 것인가?"
를 수신 서버가 판단하는 과정입니다.
8. 그래서 지금 구성에서는 이렇게 됩니다
현재 하시는 프로젝트를 예로 들면:
┌──────────────────┐
│ Ubuntu 24.04 │
│ 내 애플리케이션 │
└────────┬─────────┘
│
SMTP 인증
│
Username + Password
│
▼
┌──────────────────┐
│ AWS SES │
│ ap-northeast-2 │
└────────┬─────────┘
│
From:
service@pion79.kr
│
▼
┌──────────────────┐
│ Gmail / Outlook │
└──────────────────┘그리고 DNS 쪽에서는:
Cafe24 DNS
│
┌───────────┼────────────┐
│ │ │
DKIM SPF MX
│ │ │
▼ ▼ ▼
SES 인증 발송 인증 수신 설정이렇게 각각 역할이 있습니다.
9. SPF는 무엇인가?
SPF는 쉽게 말해서:
"pion79.kr을 대신해서 메일을 보낼 수 있는 서버가 누구인가?"
를 DNS에 등록하는 것입니다.
예를 들어 개념적으로:
pion79.kr TXT
v=spf1 include:amazonses.com ~all같은 형태가 됩니다.
그러면 Gmail이 메일을 받았을 때:
From: service@pion79.kr
이 메일은 SES에서 왔네?
pion79.kr의 SPF를 보자.
SES가 허용되어 있네.
→ SPF PASS와 같은 검사를 합니다.
10. DKIM은 더 중요합니다
DKIM은 SES가 메일에 전자서명을 붙이는 방식입니다.
개념적으로:
service@pion79.kr
│
▼
AWS SES
│
├── 메일 작성
│
└── DKIM 서명
│
▼
GmailGmail은 DNS에 등록된 공개키를 이용해서 서명을 검사합니다.
Gmail
│
├── pion79.kr DKIM 공개키 확인
│
├── 메일 서명 확인
│
└── 정상
↓
DKIM PASSAWS SES의 Easy DKIM을 이용하면 SES가 DKIM 서명을 처리하고 DNS에 필요한 CNAME을 제공해 줍니다. (AWS Documentation)
11. DMARC는 그 위에 있는 정책입니다
DMARC는 SPF와 DKIM을 이용해서:
"From에 표시된 도메인과 실제 인증된 도메인이 제대로 연결되어 있는가?"
를 판단합니다.
예:
From:
service@pion79.kr
DKIM:
pion79.kr
SPF MAIL FROM:
bounce.pion79.kr이런 구조라면 적절하게 구성했을 때 Gmail 등 수신 서버가 도메인 정렬(alignment)을 확인할 수 있습니다.
AWS도 DMARC가 SPF 또는 DKIM 중 적어도 하나의 인증 및 도메인 정렬을 요구한다고 설명합니다. (AWS Documentation)
12. 현재 하시는 bounce.pion79.kr의 역할
이 부분이 지금까지 질문하셨던 내용과 연결됩니다.
사용자가:
service@pion79.kr에서 메일을 발송한다고 해도 실제 SMTP의 MAIL FROM / Return-Path에는 별도의 도메인을 사용할 수 있습니다.
예:
From:
service@pion79.kr
MAIL FROM:
bounce@bounce.pion79.kr그러면:
pion79.kr
│
└── service@pion79.kr
bounce.pion79.kr
│
└── bounce 처리가 됩니다.
AWS SES의 custom MAIL FROM domain은 검증하는 도메인의 하위 도메인이어야 합니다. (AWS Documentation)
따라서 지금 설정하신:
bounce.pion79.kr은 상당히 적절한 구성입니다.
13. 결국 "인증"이 3개라고 생각하면 됩니다
제가 지금 구성하시는 시스템에서는 다음처럼 이해하는 것을 추천합니다.
① AWS 사용자 인증
내 서버
↓
SMTP Username
SMTP Password
↓
AWS SES누가 SES를 사용하고 있는가?
② 도메인 소유자 인증
AWS SES
↓
DNS
↓
pion79.kr정말 pion79.kr을 관리하는가?
③ 메일 자체의 인증
SES
↓
DKIM 서명
↓
Gmail
↓
SPF / DKIM / DMARC이 메일이 정말 정상적인 발신자인가?
14. 현재 pion79.kr에 적용하면
제가 권하는 최종 구조는 다음과 같습니다.
┌───────────────────────┐
│ 내 서버 │
│ Ubuntu / Node.js 등 │
└──────────┬────────────┘
│
SES SMTP 인증
│
SMTP Username/Password
│
▼
┌───────────────────────┐
│ AWS SES │
│ ap-northeast-2 │
└──────────┬────────────┘
│
┌───────────┴───────────┐
│ │
DKIM 서명 MAIL FROM
│ │
│ bounce.pion79.kr
▼ │
service@pion79.kr │
│ │
└───────────┬───────────┘
▼
Gmail
│
SPF / DKIM / DMARC
│
Inbox그리고 Cafe24 DNS에는
pion79.kr
├── SES DKIM CNAME × 3
├── SPF TXT
│
├── bounce.pion79.kr
│ ├── MX → SES
│ └── TXT SPF
│
└── 필요하면 DMARC TXT이런 형태가 됩니다.
가장 중요한 결론
SMTP 자격 증명과 DKIM 인증은 전혀 다른 것입니다.
SMTP 자격 증명
= "내 프로그램이 SES를 사용할 수 있는가?"
SES Domain Identity
= "내가 pion79.kr의 소유자인가?"
DKIM
= "SES가 보낸 이 메일은 pion79.kr의 정상적인 메일인가?"
SPF
= "이 메일을 보낸 서버가 허가된 서버인가?"
DMARC
= "From 도메인과 SPF/DKIM 인증이 제대로 일치하는가?"Cafe24 설정
1. 메일 서버(MX) 관리
보내는 서버
MX 추가
도메인(또는 호스트)
MAIL FROM 도메인이 bounce.pion79.kr와 같이 사용할 경우 사용자 지정 MAIL FROM 도메인에서 MX의 이름에서 bounce만을 입력한다.
MX 이름 : bounce.pion79.kr
메일 서버(메일 받을 서버 주소)
MX 값을 입력한다.
10 ~~~~~ amazonses.com에서10은 우선순위 이므로 숫자 10 뒤에서 값만 입력한다.
~~~~~amazonses.com
우선순위
MX 값에서 앞에 숫자를 입력한다.
보통 10
받는 서버
MX 추가
도메인(또는 호스트)에 아무것도 입력하지 않는다
sample@pion79.kr과 같이 사용하고 싶을 경우
메일 서버(메일 받을 서버 주소)
~~~~~amazonaws.com
우선순위
보통 숫자 10
2. 별칭(CNAME) 관리
도메인 별칭
CNAME에서 이름을 입력한다
~~~~~domainkey.pion79.kr
실제 도메인명
CNAME에서 값을 입력한다.
~~~~~dkim.amazonses.com
3. SPF 관리
SPF 추가 : 사용자 지정 MAIL FROM 도메인에서 TXT를 입력한다
호스트명
MAIL FROM 도메인이 bounce.pion79.kr에서 bounce만 입력한다.
SPF
"v=spf1 include:amazonses.com ~all" 에 include:amazonses.com 만을 입력한다.
4. TXT 관리
TXT 추가 : DMARC(Domain-based Message Authentication, Reporting and Conformance)에서 txt를 입력한다.
호스트명
이름에 해당하는 _dmarc.pion79.kr를 입력한다.
TXT
값을 입력한다. "v=DMARC1; p=none;"
Cafe24 설정 검토 방법 : dig 활용
1. 기본 문법
dig [DNS서버] [도메인] [레코드타입]가장 기본적인 형태:
dig pion79.kr특정 레코드를 조회:
dig MX pion79.kr
dig TXT pion79.kr
dig NS pion79.kr2. MX 조회 — 메일 서버 확인
이번에 가장 많이 사용했습니다.
dig MX pion79.kr결과에서:
ANSWER SECTION:
pion79.kr. IN MX 10 wgrpjfnj7872.iuky.mail-manager-smtp.amazonaws.com.의 의미는:
pion79.kr
↓
MX 우선순위 10
↓
wgrpjfnj7872.iuky.mail-manager-smtp.amazonaws.com즉 pion79.kr로 들어오는 메일을 어느 메일 서버가 받는지 확인합니다.
3. 서브도메인의 MX 확인
이번 SES MAIL FROM에서는:
dig MX bounce.pion79.kr을 사용했습니다.
정상적인 결과:
bounce.pion79.kr. IN MX 10 feedback-smtp.ap-northeast-2.amazonses.com.이것으로 SES Custom MAIL FROM의 MX가 제대로 설정됐는지 확인할 수 있습니다.
4. 특정 DNS 서버를 지정해서 조회
이 부분이 매우 중요합니다.
기본:
dig MX bounce.pion79.kr은 Ubuntu의 로컬 DNS resolver:
127.0.0.53을 사용합니다.
반면 Google DNS에 직접 물어보려면:
dig @8.8.8.8 MX bounce.pion79.krCloudflare DNS:
dig @1.1.1.1 MX bounce.pion79.kr즉:
dig @DNS서버 레코드타입 도메인입니다.
이번 사례에서 유용했던 이유
처음에는:
dig MX bounce.pion79.kr
→ 잘못된 값이었지만,
dig @8.8.8.8 MX bounce.pion79.kr
→ 잘못된 값이어서 인터넷상의 DNS에서도 잘못된 상태라는 것을 확인할 수 있었습니다.
수정 후에는:
dig @8.8.8.8 MX bounce.pion79.kr
→ 정상이 되었습니다.
5. TXT 조회 — SPF 확인
dig TXT bounce.pion79.kr이번에는 다음을 확인했습니다.
"v=spf1 include:amazonses.com ~all"Google DNS를 직접 확인하려면:
dig @8.8.8.8 TXT bounce.pion79.kr6. NS 조회 — 어떤 DNS 업체가 관리하는지 확인
dig NS pion79.kr이번 결과:
pion79.kr. IN NS ns1.cafe24.com.
pion79.kr. IN NS ns2.cafe24.com.
pion79.kr. IN NS ns1.cafe24.co.kr.
pion79.kr. IN NS ns2.cafe24.co.kr.따라서 pion79.kr의 권한 DNS가 Cafe24라는 것을 확인했습니다.
7. 권한 DNS 서버에 직접 물어보기
NS를 확인한 다음에는 특정 DNS 서버에 직접 질의할 수도 있습니다.
dig @ns1.cafe24.com MX bounce.pion79.kr또는:
dig @ns2.cafe24.com MX bounce.pion79.kr이 방법을 사용하면 Google/Cloudflare 같은 중간 DNS가 아니라 실제 권한 DNS가 어떤 값을 가지고 있는지 확인할 수 있습니다.
8. 이번 사례에서 사용한 명령어 요약
목적 | 명령 |
|---|---|
도메인 MX |
|
서브도메인 MX |
|
SPF/TXT |
|
DNS 관리 서버 |
|
Google DNS로 조회 |
|
Cloudflare DNS로 조회 |
|
Cafe24 DNS 직접 조회 |
|
이것만 기억하시면 됩니다
# 기본 조회
dig MX 도메인
# 특정 DNS 서버를 통해 조회
dig @DNS서버 MX 도메인
# TXT 조회
dig TXT 도메인
# NS 조회
dig NS 도메인특히 DNS 문제를 확인할 때는 dig @8.8.8.8 ...를 함께 사용하는 습관을 들이면 좋습니다. 로컬 DNS 캐시 때문에 잘못된 이전 값이 보이는 경우와 실제 공개 DNS가 잘못된 경우를 구분하는 데 매우 유용합니다.
